//@ts-nocheck
import React, {useContext, useLayoutEffect, useMemo, useReducer, useState} from 'react';
import ReactReduxContext from './context';
import {ContextValue} from './types';
import {Unsubscribe,bindActionCreators,AnyAction,ActionCreatorsMapObject} from '../redux'
import {MapStateToProps} from './';
import {CombinedState} from '../store/reducers';

/*
export default connect(
    mapStateToProps

    //法一
    ,actions //用于bindActionCreators

    //法二
    /!*,dispatch=>({
        increment(...args)=>dispatch(actions.increment(...args))
    })*!/

    //一共有七种写法

)(Counter);
*/
export default function(
  mapStateToProps: MapStateToProps<CombinedState>
  ,mapDispatchToProps: ActionCreatorsMapObject<AnyAction>|Function
){
  return function(OldComponent: React.ComponentType<any>){
    return class extends React.Component{
            static contextType = ReactReduxContext;
            unsubscribe: Unsubscribe=()=>{}
            constructor(props: any,context: ContextValue){
              super(props);
              this.state = mapStateToProps(context.store.getState());
            }
            componentDidMount(): void {
              this.unsubscribe = this.context.store.subscribe(()=>{
                this.setState(mapStateToProps(this.context.store.getState())); //setState不论你传递的是什么 只要不是==undefined的(或则不传) 就会触发更新
              })
            }
            componentWillUnmount(): void {
              this.unsubscribe();
            }
            render(){
              let dispatchProps;
              if(typeof mapDispatchToProps === 'function'){
                dispatchProps = mapDispatchToProps(this.context.store.dispatch)
              }else if(typeof mapDispatchToProps === 'object'){
                dispatchProps = bindActionCreators(mapDispatchToProps, this.context.store.dispatch);
              }
              //最终一个action(非s) 就是  increment(...args)=>dispatch(actions.increment(...args))  这样的一个函数
              return <OldComponent {...this.props} {...this.state} {...dispatchProps}/>
            }
    }
  }
}

// 函数组件版 实现
export function connect2(mapStateToProps,mapDispatchToProps){
  return function(OldComponent){
    return function(props){
      const {store} = useContext(ReactReduxContext);
      const {getState,dispatch,subscribe} = store;
      const state = getState();

      //从仓库中获取该组件对应的状态
      const stateProps = useMemo(()=>mapStateToProps(state),[state]);

      //
      const dispatchProps = useMemo(()=>{
        let dispatchProps
        if(typeof mapDispatchToProps === 'object'){
          dispatchProps = bindActionCreators(mapDispatchToProps, dispatch);
        }else if(typeof mapDispatchToProps === 'function'){
          dispatchProps = mapDispatchToProps(dispatch);

        }else {
          //如果撒都没传 就把dispatch传给用户 让他自己dispatch
          dispatchProps = {dispatch}
        }
        return dispatchProps;
      },[store.dispatch])

      //订阅
      const [,forceUpdate] = useReducer(x=>x+1/*←useReducer返回的状态如果和之前一样, 是不会触发更新的 见00hooks/06useReducer/00useReducer.tsx*/,0)
      //useEffect 执行时机是 “after render”, useLayoutEffect 能提前一点
      useLayoutEffect(()=>{
        return subscribe(forceUpdate);
      },[store])
      //↕等价
      /*const [,setState] = useState();
      useLayoutEffect(()=>{
        return subscribe(() => setState({}));
      },[store])*/

      return <OldComponent {...props} {...stateProps} {...dispatchProps}/>
    }
  }
}
